#pragma once
#include "requestor.hpp"

namespace Json_rpc
{
    namespace client
    {
        class RpcCaller
        {
        public:
            using ptr = std::shared_ptr<RpcCaller>;
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonResponseCallback = std::function<void(const Json::Value)>;
            RpcCaller(const Requestor::ptr &requestor) : _requestor(requestor)
            {
            }
            // requestor中的处理是针对BaseMessage进⾏处理的
            // ⽤于在rpccaller中针对结果的处理是针对 RpcResponse⾥边的result进⾏的


            //  同步接口
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, Json::Value &result)
            {
                // 1.组织请求
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UuidUtil::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);
                BaseMessage::ptr rsp_msg;
                // 2.发送请求
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), rsp_msg);
                if (ret == false)
                {
                    ELOG("同步RPC请求失败");
                    return false;
                }
                // 3.等待响应
                RpcResponse::ptr rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(rsp_msg);
                if (!rpc_rsp_msg)
                {
                    ELOG("RPC响应向下转换失败");
                    return false;
                }
                if (rpc_rsp_msg->rCode() != RCode::RCODE_OK)
                {
                    ELOG("请求出错: %s", errReason(rpc_rsp_msg->rCode()).c_str());
                    return false;
                }
                result = rpc_rsp_msg->result();
                return true;
            }
            // 异步接口
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params, JsonAsyncResponse &result)
            {
                // 向服务器发送异步回调请求，设置回调函数，回调函数中会传⼊⼀个promise对象，
                // 在回调函数中去堆promise设置数据
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UuidUtil::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);
                // 局部变量 回到上层会出现异常
                //  std::promise<Json::Value> json_promise;
                auto json_promise = std::make_shared<std::promise<Json::Value>>();
                result = json_promise->get_future();
                Requestor::RequestCallback cb = std::bind(&RpcCaller::Callback, this, json_promise, std::placeholders::_1);
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), cb);
                if (ret == false)
                {
                    ELOG("异步RPC请求失败");
                    return false;
                }
                return true;
            }
            // 回调接口
            bool call(const BaseConnection::ptr &conn, const std::string &method,
                      const Json::Value &params,const JsonResponseCallback &cb)
            {
                auto req_msg = MessageFactory::create<RpcRequest>();
                req_msg->setId(UuidUtil::uuid());
                req_msg->setMType(MType::REQ_RPC);
                req_msg->setMethod(method);
                req_msg->setParams(params);
                Requestor::RequestCallback req_cb = std::bind(&RpcCaller::Callback1, this, cb, std::placeholders::_1);
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req_msg), req_cb);
                if (ret == false)
                {
                    ELOG("回调RPC请求失败");
                    return false;
                }
                return true;
            }

        private:
            void Callback1(const JsonResponseCallback &cb, const BaseMessage::ptr &msg)
            {
                RpcResponse::ptr rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    ELOG("RPC响应向下转换失败");
                    return;
                }
                if (rpc_rsp_msg->rCode() != RCode::RCODE_OK)
                {
                    ELOG("请求出错: %s", errReason(rpc_rsp_msg->rCode()).c_str());
                    return;
                }
                cb(rpc_rsp_msg->result());
            }
            void Callback(std::shared_ptr<std::promise<Json::Value>> result, const BaseMessage::ptr &msg)
            {
                RpcResponse::ptr rpc_rsp_msg = std::dynamic_pointer_cast<RpcResponse>(msg);
                if (!rpc_rsp_msg)
                {
                    ELOG("RPC响应向下转换失败");
                    return;
                }
                if (rpc_rsp_msg->rCode() != RCode::RCODE_OK)
                {
                    ELOG("请求出错: %s", errReason(rpc_rsp_msg->rCode()).c_str());
                    return;
                }
                result->set_value(rpc_rsp_msg->result());
            }

        private:
            Requestor::ptr _requestor;
        };
    }
}